package com.hxl.tech.gateway.auth.exception;


import com.hxl.tech.gateway.common.constant.CheckEnum;
import com.hxl.tech.gateway.auth.dto.Response;
import com.hxl.tech.gateway.auth.util.StringUtil;
import com.hxl.tech.gateway.common.constant.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.List;


@Slf4j
@Order(-1)
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = {Throwable.class})
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleCommonException(Throwable e) {
        log.error("CommonException错误msg:{},具体异常:{}",e.toString(), e);
        return Response.createFail(e.getMessage());
    }

    @ExceptionHandler(value = {NullPointerException.class})
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleNullPointerException(NullPointerException e) {
        log.error("NullPointerException错误msg:{},具体异常:{}",e.toString(), e);
        return Response.createFail(e.getMessage());
    }

    @ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleMethodNotSupportException(HttpRequestMethodNotSupportedException e) {
        return Response.createFail(e.getMessage());
    }

    @ExceptionHandler(value = {HttpMessageNotReadableException.class})
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        return Response.createFail(e.getMessage());
    }

    @ExceptionHandler(value = {HttpMediaTypeNotSupportedException.class})
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleHttpMessageNotReadableException(HttpMediaTypeNotSupportedException e) {
        return Response.createFail(e.getMessage());
    }

    @ExceptionHandler(value = {AuthException.class})
    @ResponseStatus(value = HttpStatus.OK)
    public Response<Object> handleCustomAppException(AuthException e) {
        return Response.createFail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<ObjectError> objectErrors = e.getBindingResult().getAllErrors();
        if (objectErrors.size() > 0) {
            StringBuffer sb = new StringBuffer();
            sb.append("参数:");
            objectErrors.forEach(ObjectError -> {
                FieldError error = (FieldError) ObjectError;
                sb.append(StringUtil.camelToUnderline(error.getField()));
                sb.append("|");
                sb.append(defaultMeassage(ObjectError.getDefaultMessage()));
                sb.append(",");
            });
            sb.deleteCharAt(sb.length() - 1);
            return Response.createFail(
                    Result.E10005,
                    sb.toString());
        }
        return Response.createFail(
                Result.E10005,
                e.getBindingResult().getFieldError().getDefaultMessage());
    }


    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Response handleBindExceptionException(BindException e) {
        List<ObjectError> objectErrors = e.getAllErrors();
        if (objectErrors.size() > 0) {
            StringBuffer sb = new StringBuffer();
            sb.append("参数:");
            objectErrors.forEach(ObjectError -> {
                FieldError error = (FieldError) ObjectError;
                sb.append(StringUtil.camelToUnderline(error.getField()));
                sb.append("|");
                sb.append(defaultMeassage(ObjectError.getDefaultMessage()));
                sb.append(",");
            });
            sb.deleteCharAt(sb.length() - 1);
            return Response.createFail(
                    Result.E10005,
                    sb.toString());

        }
        return Response.createFail(
                Result.E10005,
                e.getBindingResult().getFieldError().getDefaultMessage());
    }

    private String defaultMeassage(String defaultMeassage) {
        for (CheckEnum checkEnum : CheckEnum.values()) {
            if (defaultMeassage.contains(checkEnum.getKey())) {
                return checkEnum.getValue();
            }
        }
        return defaultMeassage;
    }

}
